#ifndef BLOQUE_SEC_H_
#define BLOQUE_SEC_H_

#define PRIMERO_BLOQUE_SEC sizeof(unsigned int)

/**********************************************************************
 * bloque_sec.h
 * 
 * Descripcion: Esta clase representa un bloque de un archivo
 * secuencial indexado. Se debe crear pasandole una ref a un bloque
 * por param y luego utilizar sus metodos para ingresar u obtener
 * datos del bloque secuencial en el mismo.
 * El formato del bloque secuencial es:
 * [esp_libre:uint, (reg: TipoStruct)+]
 * Los registros se ordenan por clave de forma ascendente.
*********************************************************************/

#include "bloque.h"

class BloqueSec {
	
	private:
	
		Bloque* bloque; //Bloque que se esta empaquetando
		TipoStruct* reg_base;
				
	public:
		
		/*
		 * Constructor: Recibe el bloque a empaquetar, y el tipo base
		 * de los registros a contener.
		 */
		BloqueSec (Bloque* bloque, TipoStruct* base);
		
		/*
		 * Libera el tipo base cargado en el bloque.
		 */
		virtual ~BloqueSec();
		
		/*
		 * Devuelve el espacio libre en el bloque.
		 */
		unsigned int get_esp_libre_bloque();
		
		/*
		 * Devuelve el tamanio ocupado por registros.
		 */
		unsigned int get_tam_ocupado();
		
		/*
		 * Setea la cantidad de registros en el bloque.
		 */
		void set_cant_regs(unsigned int cant_regs);
		
		/*
		 * Devuelve la cantidad de registros del bloque.
		 */
		unsigned int get_cant_regs();
		
		/*
		 * Get Registro: Dada una clave busca el registro con la misma
		 * en el bloque. Si lo encontro lo devuelve clonado. Si no lo encontro devuelve NULL.
		 */
		TipoStruct* get_registro(TipoDato* clave);
		
		/*
		 * Devuelve una copia de la clave del primer elemento del bloque.
		 * Si no hay elementos devuelve NULL.
		 */
		TipoDato* obtener_primera_clave();
		
		/*
		 * Ingresar registro: Ingresa un nuevo registro
		 * en el lugar que corresponda segun un ordenamiento creciente por clave.
		 * Si el elemento no entra o ya esta en el nodo, 
		 * devuelve false. Sino devuelve true.
		 */
		bool ingresar_registro(TipoStruct* reg);
		
		/*
		 * Quitar registro: Dada una clave, busca el elemento en
		 * el bloque. Si lo encuentra lo remueve del mismo, haciendo
		 * una compresion, y devuelve true. Sino devuelve false.
		 */
		bool quitar_registro (TipoDato* clave);
		
		/*
		 * Buscar registro: Dada una clave, busca el registro en
		 * el bloque. Si lo encuentra devuelve la pos donde esta y devuelve true.
		 * Sino devuelve false y la pos del siguiente mayor.
		 */
		bool buscar_registro (TipoDato* clave, unsigned int &pos);
		
		/*
		 * Devuelve true si el bloque esta vacio (no tiene elementos),
		 * false en caso contrario.
		 */
		bool vacio();
		
		/*
		 * Vacia el contenido del bloque.
		 */
		void vaciar();
		  
		/*
		 * Devuelve la referencia al bloque contenido en el nodo.
		 */
		Bloque* get_bloque();
		  
		/*
		 * Ingresa el registro en el bloque this (si es distinto de NULL) y desp splitea
		 * ingresando la mitad superior en el bloque pasado como param.
		 */
		void ingresar_con_split(BloqueSec* bloque_sec, TipoStruct* reg);
		    
		/*
		 * Devuelve un clon del registro base.
		 */
		TipoDato * get_reg_base();
		
		/*
		 * Une los registros contenidos en this y los del bloque pasado como
		 * parametro en this, si los mismos entran. Sino devuelve false.
		 * Los registros del bloque pasado como parametro son removidos.
		 */
		bool unir(BloqueSec * bloque_sec);
		
		/*
		 * Dado un bloque y el bloque this, los equilibra, dejando la mitad
		 * menor en this y la mayor en el pasado como param.
		 */
		void equilibrar_bloques (BloqueSec* bloque_sec);
			      		
	private:
		
		/*
		 * Get Mitad: Devuelve la pos del registro mas cercano al medio 
		 * aritmetico del nodo.
		 */
		unsigned int get_mitad();
		
};

#endif
